home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / libkb100.zip / LIBKB-1.00 / SRC / KBLINUX.C < prev    next >
C/C++ Source or Header  |  1996-07-23  |  5KB  |  241 lines

  1. /* kblinux.c -- internal Linux stuff
  2.  * Copyright (C) 1996 Markus F.X.J. Oberhumer
  3.  * For conditions of distribution and use, see copyright notice in kb.h 
  4.  */
  5.  
  6.  
  7. #if !defined(__linux__)
  8. #  error this file is for Linux only
  9. #endif
  10.  
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <unistd.h>
  14. #include <fcntl.h>
  15. #include <termios.h>
  16. #include <sys/types.h>
  17. #include <sys/ioctl.h>
  18. #include <linux/kd.h>
  19. #include <linux/vt.h>
  20.  
  21. #include <kb.h>
  22. #include "_kb.h"
  23.  
  24.  
  25. /***********************************************************************
  26. // virtual terminal switching
  27. // termios should be saved because svgalib enables ISIG in c_lflag
  28. ************************************************************************/
  29.  
  30. int _kb_linux_switch_vt(int fd, int vt)
  31. {
  32.     int x = -1;
  33.     int r;
  34.     int my_vt;
  35.     struct vt_stat vtinfo;
  36.     long first_non_opened = 0;
  37.     struct termios t;
  38.     int sigalrm_was_running;
  39.  
  40.     if (vt <= 0)
  41.         return -1;
  42.  
  43.  
  44.     /* get current VT info */
  45.     if (ioctl(fd, VT_GETSTATE, &vtinfo) != 0)
  46.     {
  47. #if defined(KB_DEBUG)
  48.         perror("libkb VT: ioctl VT_GETSTATE");
  49. #endif
  50.         return -1;
  51.     }
  52.     my_vt = vtinfo.v_active;
  53.     if (vt == my_vt)
  54.         return 0;                /* no need to switch */
  55.  
  56.  
  57.     /* get number of virtual terminals */
  58.     if (ioctl(fd, VT_OPENQRY, &first_non_opened) != 0)
  59.     {
  60. #if defined(KB_DEBUG)
  61.         perror("libkb VT: ioctl VT_OPENQRY");
  62. #endif
  63.         return -1;
  64.     }
  65.     if (vt >= first_non_opened)
  66.         return -1;
  67.  
  68.  
  69.     /* pause the alarm() timer */
  70.     sigalrm_was_running = _kb_signal_alarm_pause();
  71.  
  72.  
  73.     /* save current termios */
  74.     r = tcgetattr(fd, &t);
  75. #if defined(KB_DEBUG)
  76.     if (r != 0)
  77.         perror("libkb VT: tcgetattr");
  78. #endif
  79. #if defined(KB_DEBUG) && (KB_DEBUG >= 3)
  80.     if (r == 0)
  81.         fprintf(stderr,"libkb VT info: fd: %d tcgetattr: "
  82.             "iflag=0x%04lx oflag=0x%04lx lflag=0x%04lx %d %d\n", 
  83.             fd, t.c_iflag, t.c_oflag, t.c_lflag,
  84.             t.c_cc[VMIN], t.c_cc[VTIME]);
  85. #endif
  86.  
  87.  
  88.     /* Do the switching.
  89.      * This will also generate a signal catched by svgalib to restore textmode.
  90.       */
  91.     if (ioctl(fd, VT_ACTIVATE, vt) != 0)
  92.     {
  93. #if defined(KB_DEBUG)
  94.         perror("libkb VT: ioctl VT_ACTIVATE");
  95. #endif
  96.     }
  97.     else
  98.     {
  99.         /* We've sucessfully returned from the VT switch. */
  100.         x = 0;
  101.  
  102.         if (_kb_flags & KB_FLAG_LINUX_VT_NO_KEY)
  103.         {
  104.             /* assume that no key is pressed */
  105.             int i;
  106.  
  107.             for (i = 0; i < 128; i++)
  108.                 if (_kb_key[i])
  109.                 {
  110.                     _kb_key[i] = 0;
  111.                     _kb_keys_pressed--;
  112.                 }
  113. #if defined(KB_DEBUG)
  114.             if (_kb_keys_pressed != 0)
  115.                 fprintf(stderr,"libkb VT: _kb_keys_pressed = %d !\n",
  116.                     _kb_keys_pressed);
  117. #endif
  118.             _kb_keys_pressed = 0;
  119.             _kb_shift &= 0x3f;    /* all shift keys off */
  120.         }
  121.     }
  122.  
  123.  
  124.     /* restore termios */
  125.     if (r == 0)
  126.     {
  127.         r = tcsetattr(fd, TCSANOW, &t);
  128. #if defined(KB_DEBUG)
  129.         if (r != 0)
  130.             perror("libkb VT: tcsetattr");
  131. #endif
  132.     }
  133.  
  134.  
  135.     /* resume the alarm() timer */
  136.     if (sigalrm_was_running == 1)
  137.         _kb_signal_alarm_resume();
  138.  
  139.     return x;
  140. }
  141.  
  142.  
  143. /***********************************************************************
  144. // Only switch if either Alt or AltGr is pressed.
  145. //
  146. // We are more restrictive than the standard behavior because 
  147. // we try to avoid the situation that a now pressed key is released
  148. // after the terminal switch and we still think it is pressed 
  149. // when we switch back to this console.
  150. // This means we prefer missing a key-press to missing a key-release
  151. // in a different console.
  152. ************************************************************************/
  153.  
  154. int _kb_linux_is_switch(int *vt, int vtnum1, int vtnum2)
  155. {
  156.     /* either Alt or AltGr must be pressed */
  157.     if (_kb_key[KB_SCAN_ALT] == _kb_key[KB_SCAN_ALTGR])
  158.         return 0;
  159.  
  160.     if (vtnum2 == 0)
  161.         vtnum2 = vtnum1 + 12;
  162.  
  163. #if 0
  164.     /* while libkb is still in beta, we always do the switch if SCRLOCK
  165.      * is pressed. If there is a bug and _kb_keys_pressed gets out
  166.      * of sync, no switching would be possible.
  167.      */
  168.     if (_kb_key[KB_SCAN_SCRLOCK])
  169.     {
  170.         *vt = _kb_key[KB_SCAN_ALT] ? vtnum1 : vtnum2;
  171.         return 1;
  172.     }
  173. #endif
  174.  
  175.     /* no other keys may be pressed */
  176.     if (_kb_keys_pressed != 1)
  177.         return 0;
  178.  
  179.     /* a valid key combination */
  180.     *vt = _kb_key[KB_SCAN_ALT] ? vtnum1 : vtnum2;
  181.     return 1;
  182. }
  183.  
  184.  
  185. /***********************************************************************
  186. // update the keyboard
  187. ************************************************************************/
  188.  
  189. int _kb_linux_update(const unsigned char *buf, int len, 
  190.                      void (*key_handler)(unsigned char))
  191. {
  192.     const unsigned char *p;
  193.     int vt;
  194.     
  195.     if (_kb_flags & KB_FLAG_LINUX_NO_VT)
  196.     {
  197.         /* optimized version for no virtual terminal switching */
  198.         for (p = buf; p < &buf[len]; p++)
  199.             key_handler(*p);
  200.         return 0;
  201.     }
  202.  
  203.     /* enable virtual terminal switching */
  204.     vt = 0;
  205.     for (p = buf; p < &buf[len]; p++)
  206.     {
  207.         int scan = *p;
  208.  
  209.         if (scan >= KB_SCAN_F1 && scan <= KB_SCAN_F12)
  210.         {
  211.             if (scan <= KB_SCAN_F10)
  212.             {
  213.                 if (_kb_linux_is_switch(&vt, scan - (KB_SCAN_F1 - 1), 0))
  214.                     continue;        /* ignore this keypress */
  215.             }
  216.             else if (scan >= KB_SCAN_F11)
  217.             {
  218.                 if (_kb_linux_is_switch(&vt, scan - (KB_SCAN_F11 - 11), 0))
  219.                     continue;        /* ignore this keypress */
  220.             }
  221.             else if (scan == KB_SCAN_LAST_CONSOLE)
  222.             {
  223.                 /* TODO: is there a system call ? */
  224.             }
  225.         }
  226.  
  227.         /* TODO: what about Incr_Console, Decr_Console ? */
  228.  
  229.         key_handler(*p);
  230.     }
  231.  
  232.     return vt;
  233. }
  234.  
  235.  
  236.  
  237. /*
  238. vi:ts=4
  239. */
  240.  
  241.